In computer systems, a storage sub-system may include a storage stack that includes multiple hardware and software components. For example, a typical stack may include a filesystem as a top component in the stack, one or more storage devices as bottom component(s) of the stack, and one or more filters between the filesystem and the storage device(s). Storage areas may be represented differently at different levels of the storage stack. For example, a storage stack may include a storage device stack that represents storage areas in terms of storage device addresses (e.g., using logical block addressing or cylinder-head-sector addressing), whether the storage devices are disks or other types of storage devices. On top of the storage device stack, the storage stack may include a volume stack that represents storage areas in terms of locations in one or more logical disks or volumes. A volume may cover a portion of a storage device, all of a storage device, or all or part of multiple storage devices.
Filters within the storage stack can provide added functionality. For example, a snapshot filter can manage snapshots of a volume. As another example, a write aggregation filter can aggregate data to be written to primary locations in one or more storage devices in a set of lazy writes (i.e., writes that are delayed until an idle or less busy time). As another example, the stack may include a disk verification filter that produces checksums of data as the data is written to a storage device. The disk verification filter can also compare those checksums with checksums of the same data as the data is read from the device, thereby verifying the integrity of the data being read. As yet another example, the stack may include a performance-boosting filter that caches data on some alternative storage media, such as RAM, a USB storage device, or flash media, that is faster than a main storage media. That cached data can be used to enhance computer performance, such as to more quickly boot a computer system.
File deletion happens frequently in computer systems. Operating system processes, such as formatting, defragmentation, recycling, temporary file deletion, and paging can produce a considerable amount of deleted file data. However, the information identifying deleted files is typically kept in the filesystem, and is not communicated to a storage device that stores the deleted file. As a result, the storage device treats both valid data and invalid data (data considered deleted by the filesystem) in its storage media the same way. Thus, the device performs all necessary operations to maintain the data, even if the data is considered invalid by the filesystem. For example, background defect management and error recovery processes may be used for hard disk drives. Merge, wear leveling and erase may be applied to solid state devices.
It has been known to send delete notifications, or trim commands, from a filesystem to a storage device to inform the storage device that particular blocks or ranges of data have been “deleted” (i.e., the blocks or ranges are now considered to be invalid data). Using this information, storage devices may be able to reduce internal operations on invalid data as a self-optimization. It has also been known to inform a storage driver when files are deleted. For example, handshake operations between a storage driver and a filesystem could involve the filesystem informing the storage driver when files get deleted, where the driver works with flash storage and does wear leveling operations for the storage. The driver could use such notifications to avoid read-modify-writes on deleted files.
In a computer system that implements volume-based storage, an entire volume sometimes needs to be reformatted, such as when a user requests reformatting or when a volume is resized. When such reformatting occurs, it is often desirable for components in a volume storage stack to perform certain actions. For example, it may be desirable for a snapshot filter that manages snapshots for the volume to delete all such snapshots and then become disabled (thereby foregoing unnecessary monitoring activities, etc.). As another example, it may be desirable for a write aggregation filter that manages lazy writes to become disabled (thereby foregoing any scheduled monitoring or lazy writes). Typically, a reformatting component that is associated with initiating the reformat will need to know the necessary commands to communicate with such storage stack components over private interfaces using commands from a separate library for each stack component. Using those commands and interfaces, the reformatting component can instruct each stack component to perform the desired actions. If one or more stack components is altered or if one or more new stack components is added, the reformatting component often must be updated so that it can properly instruct the new or altered stack component(s) to perform desired actions when an entire volume is reformatted.